package com.tanhua.dubbo.server.api;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.dubbo.config.annotation.Service;
import com.mongodb.client.result.DeleteResult;
import com.tanhua.dubbo.server.pojo.UserLike;
import com.tanhua.dubbo.server.vo.PageInfo;
import org.bson.types.ObjectId;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.redis.core.RedisTemplate;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * @author feihao
 * @version 1.0
 * @date 2021/7/10 20:21
 */

@Service(version = "1.0.0")
public class UserLikeApiImpl implements UserLikeApi {

    @Autowired
    private MongoTemplate mongoTemplate;

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    public static final String LIKE_REDIS_KEY_PREFIX = "USER_LIKE_";

    public static final String NOT_LIKE_REDIS_KEY_PREFIX = "USER_NOT_LIKE_";


    /**
     * 喜欢：
     *
     * @param userId
     * @param likeUserId
     * @return
     */
    @Override
    public Boolean  likeUser(Long userId, Long likeUserId) {

        //判断是否已经喜欢：
        if (isLike(userId, likeUserId)) {
            //已经喜欢，直接返回false;
            return false;
        }
        //保存到mongoDB:
        UserLike userLike = new UserLike();
        userLike.setId(new ObjectId());
        userLike.setUserId(userId);
        userLike.setLikeUserId(likeUserId);
        userLike.setCreated(System.currentTimeMillis());
        UserLike save = mongoTemplate.save(userLike);
        System.out.println(save);

        //用户的喜欢数据保存到redis
        //用户1：key -> USER_LIKE_1 , value -> 2, "1"
        //用户1：key -> USER_LIKE_1 , value -> 3, "1"
        //用户2：key -> USER_LIKE_2 , value -> 4, "1"
        String redisKey = getLikeRedisKey(userId);
        String hashKey = String.valueOf(likeUserId);
        redisTemplate.opsForHash().put(redisKey, hashKey, "1");

        //判断用户是否在不喜欢的列表：在的话删除redis数据：
        if (isNotLike(userId, likeUserId)) {
            redisTemplate.opsForHash().delete(getNotLikeRedisKey(userId), hashKey);
        }

        return true;
    }

    /**
     * 不喜欢：
     *
     * @param userId
     * @param likeUserId
     * @return
     */
    @Override
    public Boolean notLikeUser(Long userId, Long likeUserId) {
        //首先判断是否已经不喜欢，如果是，直接返回：
        if (isNotLike(userId, likeUserId)) {
            return false;
        }

        //操作redis,保存不喜欢的redis数据：
        String redisKey = getNotLikeRedisKey(userId);
        String hashKey = String.valueOf(likeUserId);
        redisTemplate.opsForHash().put(redisKey, hashKey, "1");

        //判断用户是否在喜欢的列表中，在的话删除mongoDB的数据，再删除redis的数据：
        if (isLike(userId, likeUserId)) {
            //删除mongoDB数据：
            Query query = Query.query(Criteria.where("userId").is(userId).and("likeUserId").is(likeUserId));
            DeleteResult remove = mongoTemplate.remove(query, UserLike.class);
            System.out.println(remove.getDeletedCount());

            //再删除redis数据：
            redisKey = getLikeRedisKey(userId);
            redisTemplate.opsForHash().delete(redisKey, hashKey);
        }
        return true;
    }


    /**
     * 是否喜欢
     *
     * @param userId
     * @param likeUserId
     * @return
     */
    public Boolean isLike(Long userId, Long likeUserId) {
        String redisKey = this.getLikeRedisKey(userId);
        String hashKey = String.valueOf(likeUserId);
        Boolean aBoolean = this.redisTemplate.opsForHash().hasKey(redisKey, hashKey);
        //如果有，直接返回true:
        if (aBoolean) {
            return true;
        }
        //redis 没查到：查询mongoDB：
        Query query = Query.query(Criteria.where("userId").is(userId).and("likeUserId").is(likeUserId));
        UserLike like = mongoTemplate.findOne(query, UserLike.class);
        if (ObjectUtil.isNotEmpty(like)) {
            //mongoDB有：返回true:
            //写道redis:
            redisTemplate.opsForHash().put(redisKey, hashKey, "1");
            return true;
        }
        return false;
    }

    /**
     * 是否不喜欢
     *
     * @param userId
     * @param likeUserId
     * @return
     */
    private Boolean isNotLike(Long userId, Long likeUserId) {
        String redisKey = this.getNotLikeRedisKey(userId);
        String hashKey = String.valueOf(likeUserId);
        return this.redisTemplate.opsForHash().hasKey(redisKey, hashKey);
    }


    /**
     * 是否互相喜欢：
     *
     * @param userId
     * @param likeUserId
     * @return
     */
    @Override
    public Boolean isMutualLike(Long userId, Long likeUserId) {

        //user喜欢likeUser,并且likeUser喜欢user,就是相互喜欢
        return isLike(userId, likeUserId) && isLike(likeUserId, userId);
    }


    /**
     * 查询喜欢的列表
     *
     * @param userId
     * @return
     */
    @Override
    public List<Long> queryLikeList(Long userId) {

        // 查询redis
        String redisKey = this.getLikeRedisKey(userId);
        Set<Object> keys = this.redisTemplate.opsForHash().keys(redisKey);
        if (CollUtil.isEmpty(keys)) {
            return ListUtil.empty();
        }

        List<Long> result = new ArrayList<>(keys.size());
        keys.forEach(o -> result.add(Convert.toLong(o)));
        return result;

    }


    /**
     * 查询不喜欢的列表
     *
     * @param userId
     * @return
     */
    @Override
    public List<Long> queryNotLikeList(Long userId) {
        // 查询redis
        String redisKey = this.getNotLikeRedisKey(userId);
        Set<Object> keys = this.redisTemplate.opsForHash().keys(redisKey);
        if (CollUtil.isEmpty(keys)) {
            return ListUtil.empty();
        }

        List<Long> result = new ArrayList<>(keys.size());
        keys.forEach(o -> result.add(Convert.toLong(o)));
        return result;
    }


    /**
     * 查询互相喜欢的数量：
     *
     * @param id
     * @return
     */
    @Override
    public int queryEachLLikeCount(Long id) {
        //先查询我喜欢的列表：获取likeUserId:
        Query query = Query.query(Criteria.where("userId").is(id));
        List<UserLike> userLikes = mongoTemplate.find(query, UserLike.class);
        //获取我喜欢的人的id：
        List<Object> likeUserIds = CollUtil.getFieldValues(userLikes, "likeUserId");

        int count = 0;
        for (Object likeUserId : likeUserIds) {
            //如果对方的喜欢列表也有我，则count++;
            Query queryLikeUser = Query.query(Criteria.where("userId").is(likeUserId).and("likeUserId").is(id));
            UserLike one = mongoTemplate.findOne(queryLikeUser, UserLike.class);
            if (ObjectUtil.isNotEmpty(one)) {
                count++;
            }
        }

        return count;
    }


    /**
     * 查询粉丝数量:
     *
     * @param id
     * @return
     */
    @Override
    public int queryFanCount(Long id) {
        //likeuserId = 此用户的id:
        Query query = Query.query(Criteria.where("likeUserId").is(id));
        List<UserLike> userLikes = mongoTemplate.find(query, UserLike.class);
        return userLikes.size();
    }


    /**
     * 查询相互喜欢列表
     * 这个就不整排序了：
     *
     * @param userId
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public PageInfo<UserLike> queryMutualLikeList(Long userId, Integer page, Integer pageSize) {


        PageInfo<UserLike> pageInfo = new PageInfo<>();
        pageInfo.setPageNum(page);
        pageInfo.setPageSize(pageSize);

        //先查询我喜欢的列表：获取likeUserId:
        Query query = Query.query(Criteria.where("userId").is(userId));
        List<UserLike> userLikes = mongoTemplate.find(query, UserLike.class);
        //获取我喜欢的人的id：
        List<Object> likeUserIds = CollUtil.getFieldValues(userLikes, "likeUserId");

        PageRequest pageRequest = PageRequest.of(page - 1, pageSize, Sort.by(Sort.Order.desc("created")));
        Query queryEachLike = Query.query(Criteria.where("userId").in(likeUserIds).and("likeUserId").is(userId)).with(pageRequest);
        List<UserLike> eachLikeList = mongoTemplate.find(queryEachLike, UserLike.class);

        pageInfo.setRecords(eachLikeList);
        return pageInfo;
    }

    /**
     * 查询我喜欢的列表
     *
     * @param userId
     * @param page
     * @param pageSize
     * @return
     */

    @Override
    public PageInfo<UserLike> queryLikeList(Long userId, Integer page, Integer pageSize) {

        PageInfo<UserLike> pageInfo = new PageInfo<>();
        pageInfo.setPageNum(page);
        pageInfo.setPageSize(pageSize);

        //查询我喜欢的人的id：
        List<Long> likeUserIdsList = queryLikeList(userId);

        //分页：
        PageRequest pageRequest = PageRequest.of(page - 1, pageSize, Sort.by(Sort.Order.desc("created")));

        //根据id查询每个喜欢的userLike:
        Query query = Query.query(Criteria.where("userId").is(userId).and("likeUserId").in(likeUserIdsList)).with(pageRequest);
        List<UserLike> userLikes = mongoTemplate.find(query, UserLike.class);

        pageInfo.setRecords(userLikes);
        return pageInfo;
    }

    /**
     * 查询粉丝列表
     *
     * @param userId
     * @param page
     * @param pageSize
     * @return
     */
    @Override
    public PageInfo<UserLike> queryFanList(Long userId, Integer page, Integer pageSize) {

        PageInfo<UserLike> pageInfo = new PageInfo<>();
        pageInfo.setPageNum(page);
        pageInfo.setPageSize(pageSize);

        PageRequest pageRequest = PageRequest.of(page - 1, pageSize, Sort.by("created"));
        Query query = Query.query(Criteria.where("likeUserId").is(userId)).with(pageRequest);
        List<UserLike> userLikes = mongoTemplate.find(query, UserLike.class);
        pageInfo.setRecords(userLikes);
        return pageInfo;
    }

    private String getLikeRedisKey(Long userId) {
        return LIKE_REDIS_KEY_PREFIX + userId;
    }

    private String getNotLikeRedisKey(Long userId) {
        return NOT_LIKE_REDIS_KEY_PREFIX + userId;
    }

}
